package math;

import java.util.List;

import data.Data;
import data.DataBig;

public class RMSE {
	
	public static double RMSE(List<Data> dataList, List<Double> predict){
		double sumsqrerr = 0.0;
		int nrat = dataList.size();
		for(int i=0; i<nrat; i++){
			byte rat = dataList.get(i).rat;
			double pred = predict.get(i);
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		double rmse = Math.sqrt(sumsqrerr / nrat);
		return rmse;
	}
	
	public static double RMSE(List<Data> dataList, double mean, double[] ubias, double[] ibias, double[] ufactor, double[] ifactor, int nfactor) {
		double sumsqrerr = 0.0;
		int nrat = dataList.size();
		
		for(int i=0; i<nrat; i++) {
			int uid = dataList.get(i).uid;
			short iid = dataList.get(i).iid;
			byte rat = dataList.get(i).rat;

			double pred = 0;
			pred += mean;
			pred += ubias[uid-1];
			pred += ibias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += ufactor[(uid-1)*nfactor+j] * ifactor[(iid-1)*nfactor+j];
			}
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		double rmse = Math.sqrt(sumsqrerr / nrat);
//		System.out.println(rmse);
		
		return rmse;
	}
	
	public static double RMSE(List<Data> posList, List<Data> negList, double posmean, double negmean, double[] uposbias, double[] iposbias, 
			double[] uposfactor, double[] iposfactor, double[] unegbias, double[] inegbias, double[] unegfactor, double[] inegfactor, int nfactor) {
		double sumsqrerr = 0.0;
		int nrat = posList.size() + negList.size();
		
		for(Data data : posList) {
			int uid = data.uid;
			short iid = data.iid;
			byte rat = data.rat;

			double pred = 0;
			pred += posmean;
			pred += uposbias[uid-1];
			pred += iposbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += uposfactor[(uid-1)*nfactor+j] * iposfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		for(Data data : negList) {
			int uid = data.uid;
			short iid = data.iid;
			byte rat = data.rat;

			double pred = 0;
			pred += negmean;
			pred += unegbias[uid-1];
			pred += inegbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += unegfactor[(uid-1)*nfactor+j] * inegfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		double rmse = Math.sqrt(sumsqrerr / nrat);
//		System.out.println(rmse);
		
		return rmse;
	}
	
	public static double RMSE(List<Data> posList, List<Data> negList, List<Data> neuList, 
			double mean, double[] ubias, double[] ibias, double[] ufactor, double[] ifactor, 
			double posmean, double[] uposbias, double[] iposbias, double[] uposfactor, double[] iposfactor, 
			double negmean, double[] unegbias, double[] inegbias, double[] unegfactor, double[] inegfactor, int nfactor) {
		
		double sumsqrerr = 0.0;
		int nrat = posList.size() + negList.size() + neuList.size();
		
		for(Data data : posList) {
			int uid = data.uid;
			short iid = data.iid;
			byte rat = data.rat;

			double pred = 0;
			pred += posmean;
			pred += uposbias[uid-1];
			pred += iposbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += uposfactor[(uid-1)*nfactor+j] * iposfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		for(Data data : negList) {
			int uid = data.uid;
			short iid = data.iid;
			byte rat = data.rat;

			double pred = 0;
			pred += negmean;
			pred += unegbias[uid-1];
			pred += inegbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += unegfactor[(uid-1)*nfactor+j] * inegfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		for(Data data : neuList) {
			int uid = data.uid;
			short iid = data.iid;
			byte rat = data.rat;

			double pred = 0;
			pred += mean;
			pred += ubias[uid-1];
			pred += ibias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += ufactor[(uid-1)*nfactor+j] * ifactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		double rmse = Math.sqrt(sumsqrerr / nrat);
		return rmse;
	}

	public static double RMSE(List<DataBig> dataList, double mean,
			double[] ubias, double[] ibias, double[] ufactor, double[] ifactor,
			byte nfactor) {
		double sumsqrerr = 0.0;
		int nrat = dataList.size();
		
		for(int i=0; i<nrat; i++) {
			int uid = dataList.get(i).uid;
			int iid = dataList.get(i).iid;
			double rat = dataList.get(i).rat;

			double pred = 0;
			pred += mean;
			pred += ubias[uid-1];
			pred += ibias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += ufactor[(uid-1)*nfactor+j] * ifactor[(iid-1)*nfactor+j];
			}
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		double rmse = Math.sqrt(sumsqrerr / nrat);
//		System.out.println(rmse);
		
		return rmse;
	}
	
	public static double RMSE(List<DataBig> posList, List<DataBig> negList, List<DataBig> neuList, 
			double mean, double[] ubias, double[] ibias, double[] ufactor, double[] ifactor, 
			double posmean, double[] uposbias, double[] iposbias, double[] uposfactor, double[] iposfactor, 
			double negmean, double[] unegbias, double[] inegbias, double[] unegfactor, double[] inegfactor, byte nfactor) {
		
		double sumsqrerr = 0.0;
		int nrat = posList.size() + negList.size() + neuList.size();
		
		for(DataBig data : posList) {
			int uid = data.uid;
			int iid = data.iid;
			double rat = data.rat;

			double pred = 0;
			pred += posmean;
			pred += uposbias[uid-1];
			pred += iposbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += uposfactor[(uid-1)*nfactor+j] * iposfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		for(DataBig data : negList) {
			int uid = data.uid;
			int iid = data.iid;
			double rat = data.rat;

			double pred = 0;
			pred += negmean;
			pred += unegbias[uid-1];
			pred += inegbias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += unegfactor[(uid-1)*nfactor+j] * inegfactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		for(DataBig data : neuList) {
			int uid = data.uid;
			int iid = data.iid;
			double rat = data.rat;

			double pred = 0;
			pred += mean;
			pred += ubias[uid-1];
			pred += ibias[iid-1];
			for(int j=0; j<nfactor; j++){
				pred += ufactor[(uid-1)*nfactor+j] * ifactor[(iid-1)*nfactor+j];
			}
			
			double err = rat - pred;
			sumsqrerr += err*err;
		}
		
		double rmse = Math.sqrt(sumsqrerr / nrat);
		return rmse;
	}

}
